home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / libsock / socket.c < prev    next >
C/C++ Source or Header  |  1997-08-02  |  8KB  |  442 lines

  1. /* socket.c:  Berkeley sockets style interface to Pilot SLP/PADP
  2.  *
  3.  * (c) 1996, D. Jeff Dionne.
  4.  * This is free software, licensed under the GNU Public License V2.
  5.  * See the file COPYING for details.
  6.  */
  7.  
  8. #include <errno.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <stdio.h>
  12. #include <signal.h>
  13. #include <fcntl.h>
  14. #include "pi-source.h"
  15. #include "pi-socket.h"
  16. #include "pi-serial.h"
  17. #include "pi-inetserial.h"
  18. #include "pi-inet.h"
  19. #include "pi-padp.h"
  20. #include "pi-cmp.h"
  21. #include "pi-dlp.h"
  22. #include "pi-syspkt.h"
  23.  
  24. static struct pi_socket *psl = (struct pi_socket *)0;
  25.  
  26. void installexit(void);
  27.  
  28. extern int dlp_trace;
  29.  
  30. static RETSIGTYPE pi_serial_onalarm(int signo);
  31.  
  32. /* Automated tickling interval */
  33. static int interval=0;
  34. static int busy=0;
  35.  
  36. /* Create a local connection endpoint */
  37.  
  38. int pi_socket(int domain, int type, int protocol)
  39. {
  40.   struct pi_socket *ps;
  41.   
  42.   if (protocol == 0) {
  43.     if (type == PI_SOCK_STREAM)
  44.       protocol = PI_PF_PADP;
  45.     else if (type == PI_SOCK_RAW)
  46.       protocol = PI_PF_SLP;
  47.   }
  48.  
  49.   if (((domain != PI_AF_SLP) && 
  50.        (domain != AF_INET)) ||
  51.       ((type  != PI_SOCK_STREAM) &&
  52.       (type   != PI_SOCK_RAW)) ||
  53.       ((protocol != PI_PF_PADP) &&
  54.        (protocol != PI_PF_SLP))) {  /* FIXME:  Need to support more */
  55.     errno = EINVAL;
  56.     return -1;
  57.   }
  58.  
  59.   ps = calloc(sizeof(struct pi_socket), 1);
  60.  
  61. #ifdef OS2
  62.   if((ps->sd = open("NUL", O_RDWR))==-1) {
  63. #else
  64.   if((ps->sd = open("/dev/null", O_RDWR))==-1) {
  65. #endif
  66.     int err = errno; /* Save errno of open */
  67.     free(ps);
  68.     errno = err;
  69.     return -1;
  70.   }
  71.   ps->mac = calloc(1, sizeof(struct pi_mac));
  72.   ps->type = type;
  73.   ps->protocol = protocol;
  74.   ps->connected = 0;
  75.   ps->mac->fd = 0;
  76.   ps->mac->ref = 1;
  77.   ps->xid = 0xff;
  78.   ps->initiator = 0;
  79.   ps->minorversion = 0;
  80.   ps->majorversion = 0;
  81.   ps->version = 0;
  82.   ps->dlprecord = 0;
  83.   ps->busy = 0;
  84.   
  85. #ifdef OS2
  86.   ps->os2_read_timeout=60;
  87.   ps->os2_write_timeout=60;
  88. #endif
  89.  
  90. #ifndef NO_SERIAL_TRACE
  91.   ps->debuglog = 0;
  92.   ps->debugfd = 0;
  93.   
  94.   if (getenv("PILOTLOG")) {
  95.     if ((ps->debuglog = getenv("PILOTLOGFILE"))==0)
  96.       ps->debuglog = "PiDebug.log";
  97.   }
  98. #endif
  99.  
  100. #ifndef NO_DLP_TRACE
  101.   if (getenv("PILOTDLP")) {
  102.     dlp_trace=1;
  103.   }
  104. #endif
  105.  
  106.   installexit();
  107.  
  108.   pi_socket_recognize(ps);
  109.   
  110.   return ps->sd;
  111. }
  112.  
  113. void pi_socket_recognize(struct pi_socket *ps)
  114. {
  115.   struct pi_socket *p;
  116.   if (!psl) psl = ps;
  117.   else {
  118.     for (p = psl; p->next; p=p->next);
  119.  
  120.     p->next = ps;
  121.   }
  122. }
  123.  
  124. /* Connect to a remote server */
  125.  
  126. int pi_connect(int pi_sd, struct sockaddr *addr, int addrlen)
  127. {
  128.   struct pi_socket *ps;
  129.   struct pi_sockaddr * pa = (struct pi_sockaddr*)addr;
  130.   enum {inet, serial} conn;
  131.  
  132.   if (!(ps = find_pi_socket(pi_sd))) {
  133.     errno = ESRCH;
  134.     return -1;
  135.   }
  136.   
  137.   conn = serial;
  138.   
  139.   if (addr->sa_family == PI_AF_SLP) {
  140.     if (pa->pi_device[0] == '.')
  141.       conn = inet;
  142.     else
  143.       conn = serial;
  144.   }
  145.   else if (addr->sa_family == AF_INET)
  146.     conn = inet;
  147.   else if (addr->sa_family == PI_AF_INETSLP)
  148.     conn = inet;
  149.     
  150.   if (conn == serial)
  151.     return pi_serial_connect(ps, addr, addrlen);
  152.   else if (conn == inet)
  153.     return pi_inet_connect(ps, addr, addrlen);
  154.     
  155.   return -1;
  156. }
  157.  
  158. /* Bind address to a local socket */
  159.  
  160. int pi_bind(int pi_sd, struct sockaddr *addr, int addrlen)
  161. {
  162.   struct pi_socket *ps;
  163.   struct pi_sockaddr * pa = (struct pi_sockaddr*)addr;
  164.   enum {inet, serial} conn;
  165.  
  166.   if (!(ps = find_pi_socket(pi_sd))) {
  167.     errno = ESRCH;
  168.     return -1;
  169.   }
  170.  
  171.   conn = serial;
  172.   
  173.   if (addr->sa_family == PI_AF_SLP) {
  174.     if (pa->pi_device[0] == '.')
  175.       conn = inet;
  176.     else
  177.       conn = serial;
  178.   }
  179.   else if (addr->sa_family == AF_INET)
  180.     conn = inet;
  181.   else if (addr->sa_family == PI_AF_INETSLP)
  182.     conn = serial;
  183.     
  184.   if (conn == serial)
  185.     return pi_serial_bind(ps, addr, addrlen);
  186.   else if (conn == inet)
  187.     return pi_inet_bind(ps, addr, addrlen);
  188.  
  189.   return -1;
  190. }
  191.  
  192. /* Wait for an incoming connection */
  193.  
  194. int pi_listen(int pi_sd, int backlog)
  195. {
  196.   struct pi_socket *ps;
  197.  
  198.   if (!(ps = find_pi_socket(pi_sd))) {
  199.     errno = ESRCH;
  200.     return -1;
  201.   }
  202.   
  203.   return ps->socket_listen(ps, backlog);
  204. }
  205.  
  206. /* Accept an incoming connection */
  207.  
  208. int pi_accept(int pi_sd, struct sockaddr *addr, int *addrlen)
  209. {
  210.   struct pi_socket *ps;
  211.  
  212.   if (!(ps = find_pi_socket(pi_sd))) {
  213.     errno = ESRCH;
  214.     return -1;
  215.   }
  216.   
  217.   return ps->socket_accept(ps, addr, addrlen);
  218. }
  219.  
  220. /* Send msg on a connected socket */
  221.  
  222. int pi_send(int pi_sd, void *msg, int len, unsigned int flags)
  223. {
  224.   struct pi_socket *ps;
  225.  
  226.   if (!(ps = find_pi_socket(pi_sd))) {
  227.     errno = ESRCH;
  228.     return -1;
  229.   }
  230.   
  231.   if (interval)
  232.     alarm(interval);
  233.   
  234.   return ps->socket_send(ps, msg, len, flags);
  235. }
  236.  
  237. /* Recv msg on a connected socket */
  238.  
  239. int pi_recv(int pi_sd, void *msg, int len, unsigned int flags)
  240. {
  241.   struct pi_socket *ps;
  242.  
  243.   if (!(ps = find_pi_socket(pi_sd))) {
  244.     errno = ESRCH;
  245.     return -1;
  246.   }
  247.  
  248.   return ps->socket_recv(ps, msg, len, flags);
  249. }
  250.  
  251. /* Wrapper for recv */
  252.  
  253. int pi_read(int pi_sd, void *msg, int len)
  254. {
  255.   return pi_recv(pi_sd, msg, len, 0);
  256. }
  257.  
  258. /* Wrapper for send */
  259.  
  260. int pi_write(int pi_sd, void *msg, int len)
  261. {
  262.   return pi_send(pi_sd, msg, len, 0);
  263. }
  264.  
  265. /* Tickle a stream connection */
  266.  
  267. int pi_tickle(int pi_sd)
  268. {
  269.   struct pi_socket *ps;
  270.  
  271.   if (!(ps = find_pi_socket(pi_sd))) {
  272.     errno = ESRCH;
  273.     return -1;
  274.   }
  275.   
  276.   return ps->socket_tickle(ps);
  277. }
  278.  
  279. /* Close a connection, destroy the socket */
  280.  
  281. int pi_close(int pi_sd)
  282. {
  283.   int result;
  284.   struct pi_socket *ps;
  285.   
  286.   if (!(ps = find_pi_socket(pi_sd))) {
  287.     errno = ESRCH;
  288.     return -1;
  289.   }
  290.  
  291.   busy++;
  292.   result = ps->socket_close(ps);
  293.   busy--;
  294.  
  295.   if (result == 0) {
  296.     if (ps == psl) {
  297.       psl = psl->next;
  298.     } else {
  299.       struct pi_socket * p;
  300.       for (p=psl; p; p=p->next) {
  301.         if (ps == p->next) {
  302.           p->next = p->next->next;
  303.           break;
  304.         }
  305.       }
  306.     }
  307.     free(ps);
  308.   }
  309.   
  310.   return result;
  311. }
  312.  
  313. /* Install an atexit handler that closes open sockets */
  314.  
  315. void pi_onexit(void)
  316. {
  317.   struct pi_socket *p, *n;
  318.   
  319.   for (p=psl; p; p=n ) {
  320.     n = p->next;
  321.     if (p->socket_close) {
  322.       pi_close(p->sd);
  323.     }
  324.   }
  325.   
  326. }
  327.  
  328. void installexit(void)
  329. {
  330.   static installedexit = 0;
  331.   
  332.   if (!installedexit)
  333.     atexit(pi_onexit);
  334.     
  335.   installedexit = 1;
  336. }
  337.  
  338. /* Get the local address for a socket */
  339.  
  340. int pi_getsockname(int pi_sd, struct sockaddr * addr, int * namelen)
  341. {
  342.   struct pi_socket *ps;
  343.  
  344.   if (!(ps = find_pi_socket(pi_sd))) {
  345.     errno = ESRCH;
  346.     return -1;
  347.   }
  348.   
  349.   if (*namelen > ps->laddrlen)
  350.     *namelen = ps->laddrlen;
  351.   memcpy(addr, &ps->laddr, *namelen);
  352.     
  353.   return 0;
  354. }
  355.  
  356. /* Get the remote address for a socket */
  357.  
  358. int pi_getsockpeer(int pi_sd, struct sockaddr * addr, int * namelen)
  359. {
  360.   struct pi_socket *ps;
  361.  
  362.   if (!(ps = find_pi_socket(pi_sd))) {
  363.     errno = ESRCH;
  364.     return -1;
  365.   }
  366.   
  367.   if (*namelen > ps->raddrlen)
  368.     *namelen = ps->raddrlen;
  369.   memcpy(addr, &ps->raddr, *namelen);
  370.     
  371.   return 0;
  372. }
  373.  
  374. int pi_version(int pi_sd)
  375. {
  376.   struct pi_socket *ps;
  377.  
  378.   if (!(ps = find_pi_socket(pi_sd))) {
  379.     errno = ESRCH;
  380.     return -1;
  381.   }
  382.   
  383.   return ps->version;
  384. }
  385.  
  386. struct pi_socket *find_pi_socket(int sd)
  387. {
  388.   struct pi_socket *p;
  389.  
  390.   for (p=psl; p; p=p->next) {
  391.     if (p->sd == sd) return p;
  392.   }
  393.  
  394.   return 0;
  395. }
  396.  
  397.  
  398. int pi_watchdog(int pi_sd, int newinterval)
  399. {
  400.   struct pi_socket *ps;
  401.  
  402.   if (!(ps = find_pi_socket(pi_sd))) {
  403.     errno = ESRCH;
  404.     return -1;
  405.   }
  406.   
  407.   ps->tickle = 1;
  408.   signal(SIGALRM, pi_serial_onalarm);
  409.   interval = newinterval;
  410.   alarm(interval);
  411.   return 0;
  412. }
  413.  
  414. static RETSIGTYPE pi_serial_onalarm(int signo)
  415. {
  416.   struct pi_socket *p, *n;
  417.   
  418.   signal(SIGALRM,pi_serial_onalarm);
  419.   
  420.   if (busy) {
  421. #ifdef DEBUG
  422.     fprintf(stderr, "world is busy. Rescheduling.\n");
  423. #endif
  424.     alarm(1);
  425.   } else
  426.     for (p=psl; p; p=n ) {
  427.       n = p->next;
  428.       if (p->connected) {
  429. #ifdef DEBUG
  430.         fprintf(stderr, "Tickling socket %d\n", p->sd);
  431. #endif
  432.         if (pi_tickle(p->sd)==-1) {
  433. #ifdef DEBUG
  434.           fprintf(stderr, " but socket is busy. Rescheduling.\n");
  435. #endif
  436.           alarm(1);
  437.         } else
  438.           alarm(interval);
  439.       }
  440.     }
  441. }
  442.